home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / gus / vts139b.zip / DEVSB.PAS < prev    next >
Pascal/Delphi Source File  |  1993-11-24  |  13KB  |  618 lines

  1. {****************************************************************************}
  2. {                                                                            }
  3. { MODULE:         DevSB                                                      }
  4. {                                                                            }
  5. { DESCRIPTION:    Device driver for the Sound Blaster sound card and         }
  6. {                 compatibles, including the Sound Blaster Pro, Sound        }
  7. {                 Booster, etc...                                            }
  8. {                 Uses both: DMA and timer polling.                          }
  9. {                                                                            }
  10. { AUTHOR:         Juan Carlos Arévalo                                        }
  11. {                                                                            }
  12. { MODIFICATIONS:  Nobody (yet ;-)                                            }
  13. {                                                                            }
  14. { HISTORY:        18-Oct-1992 Documentation. It doesn't allow the stereo     }
  15. {                             of the SB Pro yet.                             }
  16. {                 12-Nov-1992 SB Pro driver included. Speed-ups and fixes.   }
  17. {                                                                            }
  18. { (C) 1992 VangeliSTeam                                                      }
  19. {____________________________________________________________________________}
  20.  
  21. UNIT DevSB;
  22.  
  23. INTERFACE
  24.  
  25. CONST
  26.   SBDevID        = 'SBlaster-Mono';
  27.   DMAPASDevID    = 'PAS';
  28.   DMASBDevID     = 'DMA-SB-Mono';
  29.   DMASBSterDevID = 'DMA-SB-Stereo';
  30.   DMASBMixDevID  = 'Mix-DMA-SB-Stereo';
  31.   DMASBMix2DevID = 'Mix2-DMA-SB-Stereo';
  32.  
  33. CONST
  34.   SbProMixMasterVol : BYTE    = 255;   { Master volume of the SB Pro mixer.    }
  35.   SbProMixDACVol    : BYTE    = 255;   { DAC volume.                           }
  36.   SbProMixFMVol     : BYTE    = 255;   { FM music volume.                      }
  37.   SbProMixFilter    : BOOLEAN = FALSE; { TRUE = Activate SB Pro output filter. }
  38.  
  39.  
  40. PROCEDURE SBInit  (Hz: WORD);
  41. PROCEDURE SBEnd;
  42.  
  43.  
  44.  
  45.  
  46. IMPLEMENTATION
  47.  
  48. USES Dos,
  49.      SoundDevices, StrConst,
  50.      Kbd, Debugging, SoundBlaster, Hardware;
  51.  
  52.  
  53.  
  54.  
  55.  
  56. FUNCTION SBName : TDevName; FAR;
  57.   BEGIN
  58.     SBName := GetString(StrDevSBName);
  59.   END;
  60.  
  61. FUNCTION DMAPASName : TDevName; FAR;
  62.   BEGIN
  63.     DMAPASName := GetString(StrDevDMAPASName);
  64.   END;
  65.  
  66. FUNCTION DMASBName : TDevName; FAR;
  67.   BEGIN
  68.     DMASBName := GetString(StrDevDMASBName);
  69.   END;
  70.  
  71. FUNCTION DMASBSterName : TDevName; FAR;
  72.   BEGIN
  73.     DMASBSterName := GetString(StrDevDMASBSterName);
  74.   END;
  75.  
  76. FUNCTION DMASBMixName : TDevName; FAR;
  77.   BEGIN
  78.     DMASBMixName := GetString(StrDevDMASBMixName);
  79.   END;
  80.  
  81. FUNCTION DMASBMix2Name : TDevName; FAR;
  82.   BEGIN
  83.     DMASBMix2Name := GetString(StrDevDMASBMix2Name);
  84.   END;
  85.  
  86.  
  87.  
  88.  
  89. PROCEDURE SetVars;
  90.   BEGIN
  91.     SoundDevices.DSPWritePort := DSPWritePort;
  92.     SoundDevices.DSP8AckPort  := DSP8AckPort;
  93.     SoundDevices.DSPLifePort  := DSPLifePort;
  94.   END;
  95.  
  96.  
  97.  
  98.  
  99. (******)
  100.  
  101. PROCEDURE SBInit(Hz: WORD);
  102.   BEGIN
  103.     Stereo    := FALSE;
  104.     MixMethod := 0;
  105.     SbRegInit;
  106.     SetVars;
  107.     DevInitSbNonDMA(FALSE, 8);
  108.     CalcTimerData(Hz);
  109.     InitTimer;
  110.   END;
  111.  
  112.  
  113. PROCEDURE SBChgHz(Hz: WORD); FAR;
  114.   BEGIN
  115.     CalcTimerData(Hz);
  116.     InitTimer;
  117.   END;
  118.  
  119. PROCEDURE DevPoll; FAR;
  120.   BEGIN
  121.   END;
  122.  
  123.  
  124.  
  125.  
  126. PROCEDURE SBEnd; 
  127.   BEGIN
  128. {    SbRegDone;}
  129.   END;
  130.  
  131.  
  132. CONST
  133.   SBData : TSoundDevice = (
  134.     DevID      : SBDevID;
  135.     DMA        : FALSE
  136.   );
  137.  
  138.  
  139.  
  140.  
  141.  
  142. (******************* DMA Stuff *********************)
  143.  
  144.  
  145.  
  146.  
  147. CONST
  148.   OldDMAIrq : POINTER = NIL;
  149.  
  150.   DMAPlacedInBuf : WORD = 0;
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158. PROCEDURE DMAIrq; ASSEMBLER;
  159.   CONST
  160.     Old83 : BYTE = 0;
  161.   ASM
  162.                 CLI
  163.  
  164.                 PUSH    AX
  165.                 PUSH    DS
  166.                 PUSH    DX
  167.  
  168. {
  169.                 MOV     AX,$B800
  170.                 MOV     DS,AX
  171.                 INC     [WORD PTR DS:0]
  172. }
  173.  
  174.                 MOV     AX,SEG(@Data)
  175.                 MOV     DS,AX
  176.  
  177.                 MOV     DX,[DSP8AckPort]
  178.                 IN      AL,DX
  179.  
  180.                 MOV     DX,[DSPLifePort]
  181.                 IN      AL,DX
  182.  
  183.                 XOR     AL,AL
  184.                 MOV     [DMAIrqWatch],AL
  185.  
  186.                 MOV     AL,[DMAStop]
  187.                 AND     AL,AL
  188.                 JZ      @@nostop
  189.  
  190.                 MOV     [DMAStopped],AL
  191.                 MOV     [DeviceIdling],AL
  192.                 JMP     @@Fin
  193. @@nostop:
  194.                 PUSH    ES
  195.                 PUSH    BX
  196.                 PUSH    CX
  197.                 PUSH    DI
  198.                 PUSH    SI
  199. {
  200.                 PUSH    100
  201.                 PUSH    sdcSetTimeConst
  202.                 CALL    SbWriteByte
  203.  
  204.                 PUSH    100
  205.                 PUSH    232
  206.                 CALL    SbWriteByte
  207. }{
  208.                 MOV     AL,232
  209.                 MOV     [TimeConst],AL
  210. }
  211.                 CALL    SbUpdateTimeConst
  212.  
  213.                 PUSH    10000 {DMABufferSize} {64000}
  214.                 PUSH    1
  215.                 CALL    SbPlaySample
  216.  
  217.                 POP     SI
  218.                 POP     DI
  219.                 POP     CX
  220.                 POP     BX
  221.                 POP     ES
  222. @@Fin:
  223.                 MOV     AX,[SbIrq]
  224.                 CMP     AL,10
  225.                 JNZ     @@not10
  226.  
  227.                 MOV     AL,$20
  228.                 OUT     $A0,AL
  229.  
  230. @@not10:        MOV     AL,$20
  231.                 OUT     $20,AL
  232.  
  233.                 POP     DX
  234.                 POP     DS
  235.                 POP     AX
  236.  
  237.                 IRET
  238.   END;
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252. FUNCTION DMASBGetRealFreq(Hz: WORD) : WORD; FAR;
  253.   VAR
  254.     i    : WORD;
  255.     NHz1 : WORD;
  256.     NHz2 : WORD;
  257.   BEGIN
  258.     IF Hz < 4000 THEN Hz := 4000;
  259.     IF (NOT DoHiSpeed) OR (SbStereo AND NOT Sb16Detected) THEN
  260.       IF Hz > 21800 THEN Hz := 21800;
  261.  
  262.     i := Hi(65536 - (256000000 DIV Hz));
  263.     NHz1 := 1000000 DIV (256 - i);
  264.     NHz2 := 1000000 DIV (256 - i - 1);
  265.  
  266.     IF ABS(INTEGER(NHz1 - Hz)) > ABS(INTEGER(NHz2 - Hz)) THEN NHz1 := NHz2;
  267.  
  268.     DMASBGetRealFreq := NHz1;
  269.   END;
  270.  
  271.  
  272. FUNCTION DMASBProGetRealFreq(Hz: WORD) : WORD; FAR;
  273.   VAR
  274.     i    : WORD;
  275.     NHz1 : WORD;
  276.     NHz2 : WORD;
  277.   BEGIN
  278.     IF Sb16Detected THEN
  279.       BEGIN
  280.         DMASBProGetRealFreq := DMASBGetRealFreq(Hz);
  281.         EXIT;
  282.       END;
  283.  
  284.     IF Hz < 4000 THEN Hz := 4000;
  285.     IF (NOT DoHiSpeed) OR SbStereo THEN
  286.       IF Hz > 21800 THEN Hz := 21800;
  287.  
  288.     i := Hi(65536 - (128000000 DIV Hz));
  289.     NHz1 :=  500000 DIV (256 - i);
  290.     NHz2 :=  500000 DIV (256 - i - 1);
  291.  
  292.     IF ABS(INTEGER(NHz1 - Hz)) > ABS(INTEGER(NHz2 - Hz)) THEN NHz1 := NHz2;
  293.  
  294.     DMASBProGetRealFreq := NHz1;
  295.   END;
  296.  
  297.  
  298. PROCEDURE DMASBCalcTimerData(Hz: WORD);
  299.   BEGIN
  300.     CalcTimerData(PeriodicHz);
  301.  
  302.     Hz := ActiveDevice^.GetRealFreqProc(Hz);
  303.  
  304.     IF SbStereo AND NOT Sb16Detected THEN
  305.       BEGIN
  306.         TimeConst := Hi(65536 - 128000000 DIV Hz);
  307.         SoundHz   :=  500000 DIV (256 - WORD(TimeConst));
  308.       END
  309.     ELSE
  310.       BEGIN
  311.         TimeConst := Hi(65536 - 256000000 DIV Hz);
  312.         SoundHz   := 1000000 DIV (256 - WORD(TimeConst));
  313.       END;
  314.   END;
  315.  
  316.  
  317.  
  318. FUNCTION  SbMonoDetect : BOOLEAN; FAR;
  319.   BEGIN
  320.     SbRegInit;
  321.     SbProInit;
  322.     Sb16Init;
  323.     SbMonoDetect := SbRegDetect;
  324.   END;
  325.  
  326.  
  327. FUNCTION  SbStereoDetect : BOOLEAN; FAR;
  328.   BEGIN
  329.     SbRegInit;
  330.     SbProInit;
  331.     Sb16Init;
  332.     SbStereoDetect := SbProDetect OR Sb16Detect;
  333.   END;
  334.  
  335.  
  336.  
  337. PROCEDURE DMASBInit(Hz: WORD);
  338.   BEGIN
  339.     SbStereo := Stereo;
  340.  
  341.     SbRegInit;
  342.     SbProInit;
  343.     Sb16Init;
  344.  
  345.     SbWriteByte(SbDefTimeout, sdcTurnOnSpeaker);
  346. {
  347.     IF PORT[$22E] = 0 THEN;
  348. }
  349.     SetVars;
  350.  
  351.     DMAChannel := SbDMAChan;
  352.  
  353.     DevInitSbDMA(SbStereo, 8);
  354.  
  355.     IF OldDMAIrq = NIL THEN BEGIN
  356.       OldDMAIrq := SetIRQVector(SbIrq, @DMAIrq);
  357.       EnableIRQ(SbIrq);
  358.     END;
  359.  
  360.     SbProSetStereo(SbStereo);
  361.     DMASBCalcTimerData(Hz);
  362.  
  363.     DMASet(SbDMAChan, $58, DMABuffer, DMABufferSize);
  364.  
  365.     SbUpdateTimeConst;
  366.     SbPlaySample(10 {DMABufferSize}, FALSE);
  367.  
  368.     InitTimer;
  369.  
  370.     DMAStopped := FALSE;
  371.     DMAStop    := FALSE;
  372.   END;
  373.  
  374.  
  375. PROCEDURE DMASBMonoInit(Hz: WORD); FAR;
  376.   BEGIN
  377.     Stereo    := FALSE;
  378.     DevBits   := 8;
  379.     MixMethod := 0;
  380.     DMASbInit(Hz);
  381.   END;
  382.  
  383.  
  384. PROCEDURE DMASBSterInit(Hz: WORD); FAR;
  385.   BEGIN
  386.     Stereo    := TRUE;
  387.     DevBits   := 8;
  388.     MixMethod := 1;
  389.     DMASbInit(Hz);
  390.   END;
  391.  
  392.  
  393. PROCEDURE DMASBMixInit(Hz: WORD); FAR;
  394.   BEGIN
  395.     Stereo    := TRUE;
  396.     DevBits   := 8;
  397.     MixMethod := 2;
  398.     DMASbInit(Hz);
  399.   END;
  400.  
  401.  
  402. PROCEDURE DMASBMix2Init(Hz: WORD); FAR;
  403.   BEGIN
  404.     Stereo    := TRUE;
  405.     DevBits   := 8;
  406.     MixMethod := 3;
  407.     DMASbInit(Hz);
  408.   END;
  409.  
  410.  
  411. PROCEDURE DMASBChgHz(Hz: WORD); FAR;
  412.   BEGIN
  413.     DMASBCalcTimerData(Hz);
  414.   END;
  415.  
  416.  
  417. PROCEDURE DMASBEnd; FAR;
  418.   BEGIN
  419.  
  420.     IF OldDMAIrq <> NIL THEN BEGIN
  421.       DMAStopped := FALSE;
  422.       DMAStop    := TRUE;
  423.  
  424.       ASM PUSHF; STI END;
  425.  
  426.       WHILE (NOT DMAStopped) AND (NOT DeviceIdling) AND (NOT KbdKeyPressed) DO;
  427.  
  428.       ASM POPF END;
  429. {
  430.       DMAReset(SbDMAChan);
  431. }
  432.       SetIRQVector(SbIrq, OldDMAIrq);
  433.       OldDMAIrq := NIL;
  434. {
  435.       SbWriteByte($D3, 100);
  436. }
  437.     END;
  438.     DisableIRQ(SbIrq);
  439.  
  440.   END;
  441.  
  442.  
  443.  
  444.  
  445.  
  446. VAR
  447.   SaveHiSpeed : BOOLEAN;
  448.  
  449. PROCEDURE DMAPASMonoInit(Hz: WORD); FAR;
  450.   BEGIN
  451.     IF OldDMAIrq = NIL THEN
  452.       BEGIN
  453.         SaveHiSpeed := SbHiSpeed;
  454.         SbHiSpeed := FALSE;
  455.       END;
  456.  
  457.     Stereo     := FALSE;
  458.     DevBits    := 8;
  459.     MixMethod  := 0;
  460.     DMASbInit(Hz);
  461.   END;
  462.  
  463.  
  464.  
  465.  
  466. PROCEDURE DMAPASEnd; FAR;
  467.   BEGIN
  468.  
  469.     IF OldDMAIrq <> NIL THEN BEGIN
  470.       DMAStopped := FALSE;
  471.       DMAStop    := TRUE;
  472.  
  473.       ASM PUSHF; STI END;
  474.  
  475.       WHILE (NOT DMAStopped) AND (NOT DeviceIdling) AND (NOT KbdKeyPressed) DO;
  476.  
  477.       ASM POPF END;
  478. {
  479.       DMAReset(SbDMAChan);
  480. }
  481.       SetIRQVector(SbIrq, OldDMAIrq);
  482.       OldDMAIrq := NIL;
  483. {
  484.       SbWriteByte($D3, 100);
  485. }
  486.       SbHiSpeed  := SaveHiSpeed;
  487.     END;
  488.     DisableIRQ(SbIrq);
  489.  
  490.   END;
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504. CONST
  505.   DMAPASData : TSoundDevice = (
  506.     DevID      : DMAPASDevID;
  507.     DMA        : TRUE
  508.   );
  509.  
  510.  
  511.   DMASBData : TSoundDevice = (
  512.     DevID      : DMASBDevID;
  513.     DMA        : TRUE
  514.   );
  515.  
  516.  
  517. CONST
  518.   DMASBSterData : TSoundDevice = (
  519.     DevID      : DMASBSterDevID;
  520.     DMA        : TRUE
  521.   );
  522.  
  523.  
  524. CONST
  525.   DMASBMixData : TSoundDevice = (
  526.     DevID      : DMASBMixDevID;
  527.     DMA        : TRUE
  528.   );
  529.  
  530.  
  531. CONST
  532.   DMASBMix2Data : TSoundDevice = (
  533.     DevID      : DMASBMix2DevID;
  534.     DMA        : TRUE
  535.   );
  536.  
  537.  
  538.  
  539.  
  540. (******)
  541.  
  542. BEGIN
  543.  
  544.   WITH SBData DO BEGIN
  545.     Name            := SBName;
  546.     AutoDetect      := SbRegDetect;
  547.     InitRut         := SBInit;
  548.     ChgHzProc       := SBChgHz;
  549.     GetRealFreqProc := GetRealFreq;
  550.     TimerHandler    := SoundDevices.TimerHandler;
  551.     PollRut         := DevPoll;
  552.     EndRut          := SBEnd;
  553.   END;
  554.  
  555.   WITH DMASBData DO BEGIN
  556.     Name            := DMASBName;
  557.     AutoDetect      := SbMonoDetect;
  558.     InitRut         := DMASBMonoInit;
  559.     ChgHzProc       := DMASBChgHz;
  560.     GetRealFreqProc := DMASBGetRealFreq;
  561.     TimerHandler    := DMATimerHandler;
  562.     PollRut         := DevPoll;
  563.     EndRut          := DMASBEnd;
  564.   END;
  565.  
  566.   WITH DMAPASData DO BEGIN
  567.     Name            := DMAPASName;
  568.     AutoDetect      := SbMonoDetect;
  569.     InitRut         := DMAPASMonoInit;
  570.     ChgHzProc       := DMASBChgHz;
  571.     GetRealFreqProc := DMASBGetRealFreq;
  572.     TimerHandler    := DMATimerHandler;
  573.     PollRut         := DevPoll;
  574.     EndRut          := DMAPASEnd;
  575.   END;
  576.  
  577.   WITH DMASBSterData DO BEGIN
  578.     Name            := DMASBSterName;
  579.     AutoDetect      := SbStereoDetect;
  580.     InitRut         := DMASBSterInit;
  581.     ChgHzProc       := DMASBChgHz;
  582.     GetRealFreqProc := DMASBProGetRealFreq;
  583.     TimerHandler    := DMATimerHandler;
  584.     PollRut         := DevPoll;
  585.     EndRut          := DMASBEnd;
  586.   END;
  587.  
  588.   WITH DMASBMixData DO BEGIN
  589.     Name            := DMASBMixName;
  590.     AutoDetect      := SbStereoDetect;
  591.     InitRut         := DMASBMixInit;
  592.     ChgHzProc       := DMASBChgHz;
  593.     GetRealFreqProc := DMASBProGetRealFreq;
  594.     TimerHandler    := DMATimerHandler;
  595.     PollRut         := DevPoll;
  596.     EndRut          := DMASBEnd;
  597.   END;
  598.  
  599.   WITH DMASBMix2Data DO BEGIN
  600.     Name            := DMASBMix2Name;
  601.     AutoDetect      := SbStereoDetect;
  602.     InitRut         := DMASBMix2Init;
  603.     ChgHzProc       := DMASBChgHz;
  604.     GetRealFreqProc := DMASBProGetRealFreq;
  605.     TimerHandler    := DMATimerHandler;
  606.     PollRut         := DevPoll;
  607.     EndRut          := DMASBEnd;
  608.   END;
  609.  
  610.   InitDevice(@DMASBMix2Data);
  611.   InitDevice(@DMASBMixData);
  612.   InitDevice(@DMASBSterData);
  613.   InitDevice(@DMASBData);
  614.   InitDevice(@DMAPASData);
  615.   InitDevice(@SBData);
  616.  
  617. END.
  618.